﻿// Ex9.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//你的继承和多态学得像一坨史。现在，你应当写一个基础的练习。
//试着写一个shape类，其中包含:
// 1.形状的属性（边长、周长、面积等）与对应的成员函数;
// 2.运算符重载实现输出图形信息和面积比较，体现继承和多态。
// 3.开始吧！

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class shape {
public:
    shape() :para(0), area(0){}

    void setLength(double l)    //设置长度的函数。因为通过派生类指针调用set时，无需重载，实现set功能，只需调用该版本的set即可。
    {
        length = l;
        cout << "called 0-1" << endl;
    }
    void setWidth(double w)//设置宽度的函数。同上。
    {
        width = w;
        cout << "called 0-2" << endl;
    }
    void setArea(double a)    //设置长度的函数。纯粹提供一个接口。
    {
        area = a;
        cout << "called 0-3" << endl;
    }
    void setPara(double p)//设置周长的函数。同上。
    {
        para = p;
        cout << "called 0-4" << endl;
    }

    virtual double getPara() = 0;//由于不同图形计算面积方法各异，因此需要重写，故使用virtual。
    virtual double getArea() = 0;//同上。
    virtual string getShape() = 0;//返回图形信息，用于运算符重载。
    friend ostream& operator<<(ostream& os,shape& sp)//重载一个<<运算符，便于各个形状的输出。
    {
        os << "Shape = " << sp.getShape() << ",Parametre = " << sp.para << ",Area = " << sp.area << endl;
        return os;
    }


    double getL()//get同理。
    {
        return length;
    }

    double getW()//同上。
    {
        return width;
    }

private:
    double length = 0;
    double width = 0;
    double para;//周长
    double area;//面积
    
};

class Rect :public shape {//长方形
public:
    Rect():shape(){}

    double getArea()//重写的面积函数
    {
        setArea(getL() * getW());
        cout << "called 1-1" << endl;
        return getL() * getW();
    }
    double getPara()//重写的周长函数
    {
        setPara(2 * (getL() + getW()));
        cout << "called 1-2" << endl;
        return 2 * (getL() + getW());
    }
    string getShape()
    {
        return "Rectangle";
    }
};

class rtTri :public shape {//直角三角形
public:
    rtTri():shape() {}

    double getArea()//重写的面积函数
    {
        setArea(0.5 * getL() * getW());
        cout << "called 2-1" << endl;
        return 0.5 * getL() * getW();
    }
    double getPara()//重写的周长函数
    {
        setPara((getL() + getW() + sqrt(getL() * getL() + getW() * getW())));
        cout << "called 2-2" << endl;
        return ((getL() + getW() + sqrt(getL() * getL() + getW() * getW())));//这真是一坨，不是吗？
    }
    string getShape()
    {
        return "RectaTriangle";
    }
};

class eqTri :public shape {//等边三角形
public:
    eqTri() :shape() {}

    double getArea()//重写的面积函数
    {
        setArea(0.5 * getL() * getL());
        return 0.5 * getL() * getL();
    }
    double getPara()//重写的周长函数
    {
        setPara(3 * getL());
        return (3 * getL());//这真是一坨，不是吗？
    }
    string getShape()
    {
        return "EqTriangle";
    }
};

int main()
{
    int s = 0;
    int& s0 = s;
    Rect s1;
    rtTri s2;
    rtTri s3;
    eqTri s4;
    vector<shape*>shapes = {};
    shapes.push_back(&s1);
    shapes.push_back(&s2);
    shapes.push_back(&s3);
    shapes.push_back(&s4);
    for (auto const& s : shapes)
    {
        s->setLength(++s0);
        s->setWidth(++s0);
    }
    for (auto const& s : shapes)
    {
        cout << *s;
    }
    std::cout << "Hello World!\n";
}

